using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.Runtime;
using Citrix.WorkflowStudio.Common;
using Citrix.WorkflowStudio.CustomActivities.Designers;
using Citrix.WorkflowStudio.CustomActivities.Editors;
using Citrix.WorkflowStudio.CustomActivities.Serializers;
using Citrix.WorkflowStudio.User;

namespace Citrix.WorkflowStudio.Activities.WFSIISActivites
{
	#region Attribute Definitions and Comments
	[Designer(typeof(BaseActivityDesigner))]
	[DisplayNameAttribute(@"Add Site Binding (HTTP)")]
	[Description(@"This activity will allow you to add an additional http binding to an existing site (HTTP Only).")]
    [ActivityTreePath(@"IIS/IIS7")]
	[ActivityValidator(typeof(IIS7AddBindingValidator))]
	[ToolboxBitmapAttribute(typeof(IIS7AddBinding), @"Resources.IIS7AddBinding16.png")]
	[BaseActivityDesigner(ImageResourceName = @"Resources.IIS7AddBinding32.png", AssemblyType = typeof(IIS7AddBinding))]
	#endregion Attribute Definitions and Comments

	public partial class IIS7AddBinding : ActivityBase
	{
		#region Constructor
		public IIS7AddBinding()
		{
			InitializeComponent();

            this.Port = 8080;
		}
		#endregion Constructor

        public static DependencyProperty SiteNameProperty = DependencyProperty.Register("SiteName", typeof(String), typeof(IIS7AddBinding));
        [DefaultValue("")]
        [Category(@"Binding Information")]
        [DisplayName(@"Web Site Name")]
        [Description(@"This is the site name that you wish to add the binding to (Display name as seen in the IIS Administration UI.")]
        [Browsable(true)]
        [InputAttribute]
        [EditorAttribute(typeof(TextEditor), typeof(UITypeEditor))]
        public String SiteName
        {
            get
            {
                return ((String)(base.GetValue(SiteNameProperty)));
            }
            set
            {
                base.SetValue(SiteNameProperty, value);
            }
        }
        public static DependencyProperty ServerNameProperty = DependencyProperty.Register("ServerName", typeof(String), typeof(IIS7AddBinding));
        [DefaultValue("")]
        [Category(@"Binding Information")]
        [DisplayName(@"Server Name")]
        [Description(@"Enter the name of the server where the site is located. This can be either a name or IP address.")]
        [Browsable(true)]
        [InputAttribute]
        [EditorAttribute(typeof(TextEditor), typeof(UITypeEditor))]
        public String ServerName
        {
            get
            {
                return ((String)(base.GetValue(ServerNameProperty)));
            }
            set
            {
                base.SetValue(ServerNameProperty, value);
            }
        }

        public static DependencyProperty PortProperty = DependencyProperty.Register("Port", typeof(Int32), typeof(IIS7AddBinding));
        [DefaultValue(8080)]
        [Category(@"Binding Information")]
        [DisplayName(@"Port")]
        [Description(@"This is the port that you wish the new binding to listen on.")]
        [Browsable(true)]
        [InputAttribute]
        public int Port
        {
            get
            {
                return ((Int32)(base.GetValue(PortProperty)));
            }
            set
            {
                base.SetValue(PortProperty, value);
            }
        }

        public static DependencyProperty IPAddressProperty = DependencyProperty.Register("IPAddress", typeof(string), typeof(IIS7AddBinding));
        [DefaultValue("*")]
        [Category(@"Binding Information")]
        [DisplayName(@"IP Address")]
        [Description(@"This is the IP address that you would like the binding to listen on. If yo dont enter anything it will listen on all configured IP Addresses.")]
        [Browsable(true)]
        [InputAttribute]
        [EditorAttribute(typeof(TextEditor), typeof(UITypeEditor))]
        public string IPAddress
        {
            get
            {
                return ((string)(base.GetValue(IPAddressProperty)));
            }
            set
            {
                base.SetValue(IPAddressProperty, value);
            }
        }

        public static DependencyProperty HostHeaderProperty = DependencyProperty.Register("HostHeader", typeof(string), typeof(IIS7AddBinding));
        [DefaultValue("")]
        [Category(@"Binding Information")]
        [DisplayName(@"Host Header")]
        [Description(@"This is the optional host header that you can have the binding listen for.")]
        [Browsable(true)]
        [InputAttribute]
        [EditorAttribute(typeof(TextEditor), typeof(UITypeEditor))]
        public string HostHeader
        {
            get
            {
                return ((string)(base.GetValue(HostHeaderProperty)));
            }
            set
            {
                base.SetValue(HostHeaderProperty, value);
            }
        }
        // The logic for your activity belongs in the Execute method below
		#region Activity Execution Logic
		protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
		{
			// Expand all string properties with the required attribute
			ExpandStringProperties(executionContext.Activity);

			try
			{
                Microsoft.Web.Administration.ServerManager pServerManager = Microsoft.Web.Administration.ServerManager.OpenRemote(this.ServerName);

                Microsoft.Web.Administration.Site pExistingSite = pServerManager.Sites[this.SiteName];

                System.Text.StringBuilder pBindingInfo = new System.Text.StringBuilder();
                pBindingInfo.Append(this.IPAddress);
                pBindingInfo.Append(":");
                pBindingInfo.Append(this.Port.ToString());
                pBindingInfo.Append(":");
                pBindingInfo.Append(this.HostHeader);

                pExistingSite.Bindings.Add(pBindingInfo.ToString(), "http");

                pServerManager.CommitChanges();
			}

			catch (Exception e)
			{
				String errmsg = "An error has occurred. The error is \"" + e.Message.ToString() + "\"";

				if (e.InnerException != null && e.InnerException.ToString().Length > 0)
					errmsg += "\nAdditional error info: \"" + e.InnerException.ToString() + "\"";

				throw new Exception(errmsg);

				// NOTE: Do not set ActivityExecutionStatus to Faulting if you throw an exception manually.
			}

			// You need to conclude your Execute method by setting the ActivityExecutionStatus.
			// Valid values are:
			//	Canceling
			//	Closed
			//	Compensating
			//	Executing
			//	Faulting
			//	Initialized
			return ActivityExecutionStatus.Closed;
		}
		#endregion Activity Execution Logic
	}

	// Property validation code
	//     In the Validate method you have to create a new instance of the activity class above,
	//     create a new ValidationErrorCollection instance, and then write the code to process the validation.
	//     For each validation error/warning, you need to add the error/warning to the ValidationErrorCollection.
	//     Finally, the Validate method should return the ValidationErrorCollection object.
	#region Validation Logic
	public class IIS7AddBindingValidator : ActivityValidator
	{
		public override ValidationErrorCollection Validate(ValidationManager manager, object obj)
		{
			IIS7AddBinding MyActivity = obj as IIS7AddBinding;
			ValidationErrorCollection errs = new ValidationErrorCollection();
            
			if ((MyActivity != null) && (MyActivity.Parent != null))
			{
                if (MyActivity.ServerName == null || MyActivity.ServerName.Length == 0)
                {
                    errs.Add(new ValidationError(@"You need to specify a server address where the web site exists. Please set the 'Server Name' property", 101, false, @"ServerNameProperty"));
                }
                if (MyActivity.SiteName == null || MyActivity.SiteName.Length == 0)
                {
                    errs.Add(new ValidationError(@"You need to specify a web site name to add the binding to. Please set the 'Site Name' property", 101, false, @"SiteNameProperty"));
                }

			#region Sample Property Validation
			//if (MyActivity.StringProperty == null || MyActivity.StringProperty.Length == 0)
			//  errs.Add(new ValidationError(@"You should specify a value for the 'StringProperty' property.", 101, true, @"StringProperty"));

			//if (!GlobalUtilities.StringValidates(MyActivity, MyActivity.StringProp, IIS7AddBinding.StringPropProperty))
			//  errs.Add(new ValidationError(@"You must specify a value for the 'StringProp' property.", 101, false, @"StringProp"));

			//if (!GlobalUtilities.BooleanValidates(MyActivity.BooleanProp))
			//  errs.Add(new ValidationError(@"You must specify a valid value for the 'BooleanProp' property.", 101, false, @"BooleanProp"));

			//if (!GlobalUtilities.Int32Validates(MyActivity.IntegerProp, 1, 65000))	// Uses min = 1 and max = 65000
			//if (!GlobalUtilities.Int32Validates(MyActivity.IntegerProp))			    // Allows any valid Integer
			//  errs.Add(new ValidationError(@"You must specify a value for the 'IntegerProp' property.", 101, false, @"IntegerProp"));

			//if (!GlobalUtilities.DoubleValidates(MyActivity.DoubleProp, 1.0, 999.9))	// Uses min = 1.0 and max = 999.9
			//if (!GlobalUtilities.DoubleValidates(MyActivity.DoubleProp))			    // Allows any valid Double
			//  errs.Add(new ValidationError(@"You must specify a value for the 'DoubleProp' property.", 101, false, @"DoubleProp"));

			//if (!GlobalUtilities.DecimalValidates(MyActivity.DecimalProp, 1.0m, 1234.5m))	// Uses min = 1.0 and max = 1234.5
			//if (!GlobalUtilities.DecimalValidates(MyActivity.DecimalProp))		        // Allows any valid Decimal
			//  errs.Add(new ValidationError(@"You must specify a value for the 'DecimalProp' property.", 101, false, @"DecimalProp"));
			#endregion Sample Property Validation
			}
            
			#region StopOnError Validation
        	        if (!MyActivity.StopOnError)
	                {
        	            Boolean found = false;
	                    if (MyActivity.Activities != null)
        	            {
                	        for (int i = 0; ((i < MyActivity.Activities.Count) && (!found)); i++)
                        	{
	                            if (MyActivity.Activities[i].GetType() == typeof(System.Workflow.ComponentModel.FaultHandlersActivity))
        	                    {
                	                found = true;
                        	        CompositeActivity faultHandlers = (CompositeActivity)(MyActivity.Activities[i]);
                                	if ((faultHandlers.Activities == null) || (faultHandlers.Activities.Count == 0))
	                                    errs.Add(new ValidationError("The 'Stop On Error' property is set to 'false' but the auto-generated faultHandlerActivity has been manually deleted.", 101, false, "StopOnError"));
        	                    }
                	        }
                        	if (!found)
	                            errs.Add(new ValidationError("The 'Stop On Error' property is set to 'false' but the auto-generated faultHandlersActivity has been manually deleted.", 101, false, "StopOnError"));
        	            }
                	}
			#endregion StopOnError Validation

            
			// Return the ValidationErrorCollection
			return errs;
		}
	}
	#endregion Validation Logic
}
